home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Freelog Special Edition 10
/
FreelogHS10.iso
/
Buzz
/
Buzz_Advanced_Pack.exe
/
{app}
/
Dev
/
MidiRecExample.txt
< prev
next >
Wrap
Text File
|
2001-08-27
|
4KB
|
255 lines
// allocated track:
// 1. same LastNote if note not in pattern
// 2. first free with no note in pattern
// 3. first free
// 4. track with oldest high note (C6+)
// 5. track with oldest mid note (C3+)
// 6. track with oldest note
int mi::AllocateTrack(CSequence *pseq, int note)
{
for (int c = 0; c < numTracks; c++)
{
if (Tracks[c].LastNote == note)
{
if (pseq != NULL)
{
byte *pdata = (byte *)pCB->GetPlayingRow(pseq, 2, c);
if (*pdata == NOTE_NO)
return c;
}
}
}
int best = -1;
for (c = 0; c < numTracks; c++)
{
if (Tracks[c].Voices[Tracks[c].FreeVoice^1].State == CVoice::inactive)
{
if (pseq != NULL)
{
byte *pdata = (byte *)pCB->GetPlayingRow(pseq, 2, c);
if (*pdata == NOTE_NO)
return c;
}
if (best == -1)
best = c;
}
}
if (best != -1)
return best;
// if we got here it means all voices are active
int oldt = -1;
// check high
for (c = 0; c < numTracks; c++)
{
if (Tracks[c].LastNote >= ((6 << 4) + 1)) // >= C6
{
int at = Tracks[c].Voices[Tracks[c].FreeVoice^1].ActiveTime;
if (at > oldt)
{
oldt = at;
best = c;
}
}
}
if (best != -1)
return best;
// check mid
for (c = 0; c < numTracks; c++)
{
if (Tracks[c].LastNote >= ((3 << 4) + 1)) // >= C3
{
int at = Tracks[c].Voices[Tracks[c].FreeVoice^1].ActiveTime;
if (at > oldt)
{
oldt = at;
best = c;
}
}
}
if (best != -1)
return best;
// check low
for (c = 0; c < numTracks; c++)
{
int at = Tracks[c].Voices[Tracks[c].FreeVoice^1].ActiveTime;
if (at > oldt)
{
oldt = at;
best = c;
}
}
assert(best != -1);
return best;
}
void miex::MidiControlChange(int const ctrl, int const channel, int const value)
{
// TODO: check channel
if (ctrl != 64) // 64 = sustain pedal
return;
if (value < 64)
{
CSequence *pseq;
int stateflags = pmi->pCB->GetStateFlags();
if (stateflags & SF_PLAYING && stateflags & SF_RECORDING)
pseq = pmi->pCB->GetPlayingSequence(pmi->ThisMachine);
else
pseq = NULL;
int notedelay = pmi->pMasterInfo->PosInTick * 24 / pmi->pMasterInfo->SamplesPerTick;
pmi->SustainPedal = false;
for (int c = 0; c < pmi->numTracks; c++)
{
if (pmi->Tracks[c].Note != NOTE_NO && pmi->Tracks[c].Sustained)
{
pmi->Tracks[c].Sustained = false;
pmi->MidiNoteOff(c, pseq, notedelay);
}
}
}
else
{
pmi->SustainPedal = true;
}
}
void mi::MidiNoteOff(int c, CSequence *pseq, int notedelay)
{
Tracks[c].NoteOff();
if (pseq != NULL)
{
byte *pdata = (byte *)pCB->GetPlayingRow(pseq, 2, c);
if (notedelay > 0)
{
if (pdata[0] != NOTE_NO)
{
if (pdata[2] == 0x0d)
{
int ondelay = pdata[3] >> 1;
pdata[2] = 0x0b;
pdata[3] = (ondelay << 4) | (notedelay >> 1);
}
else
{
// ondelay = 0
pdata[2] = 0x0b;
pdata[3] = (notedelay >> 1);
}
}
else
{
pdata[0] = NOTE_OFF;
pdata[2] = 0x0d;
pdata[3] = (byte)notedelay;
}
}
else
{
pdata[0] = NOTE_OFF;
}
}
}
void mi::MidiNote(int const channel, int const value, int const velocity)
{
// TODO: check channel
if (value / 12 > 9)
return;
byte n = (((value / 12)-1) << 4) | ((value % 12) + 1);
CSequence *pseq;
int stateflags = pCB->GetStateFlags();
if (stateflags & SF_PLAYING && stateflags & SF_RECORDING)
pseq = pCB->GetPlayingSequence(ThisMachine);
else
pseq = NULL;
int notedelay = pMasterInfo->PosInTick * 24 / pMasterInfo->SamplesPerTick;
if (velocity > 0)
{
int c = AllocateTrack(pseq, n);
Tracks[c].Note = n;
Tracks[c].Velocity = velocity;
Tracks[c].NoteOn();
if (pseq != NULL)
{
byte *pdata = (byte *)pCB->GetPlayingRow(pseq, 2, c);
pdata[0] = n;
pdata[1] = velocity;
if (notedelay > 0)
{
pdata[2] = 0x0d;
pdata[3] = (byte)notedelay;
}
}
}
else
{
for (int c = 0; c < numTracks; c++)
{
if (Tracks[c].Note == n)
{
if (SustainPedal)
Tracks[c].Sustained = true;
else
MidiNoteOff(c, pseq, notedelay);
break;
}
}
}
}